package com.study.java._01generic;

import java.util.ArrayList;
import java.util.List;

/**
 * <pre>
 *     author : slx
 *     time   : 2020/11/17
 *     desc   : 泛型擦除
 * </pre>
 */
public class _04Demo {
    public static void main(String[] args) {
        // 泛型擦除的影响
        // 1.泛型擦除后，Integer->Object,但是Object不能存放基本int类型
        List<Integer> intList = new ArrayList<>();
        // 2.不能使用instanceof,只能使用List<?>
        List<String> sList = new ArrayList<>();
        // 编译报错，因为<String>被擦除
       /*if (sList instanceof List<String>) {

        }*/
        new _04Demo().testArray();
    }

    public void testArray() {
        // 4.无法创建泛型数组，因为数组是协变的，擦除后类型未知，不满足协变
        // Apple是Fruit的父类则Apple[]是Fruit[]的父类，称为数组协变
        Fruit[] fruits = new Fruit[10];
        Apple[] apples = new Apple[10];
        fruits = apples;
        //fruits[0] = new Banner(); // 编译正常，运行直接报错
    }

    class Fruit {
    }

    class Apple extends Fruit {
    }

    class Banner extends Fruit {
    }

    // 3.泛型类型方法冲突
    class MethodThing<T> {
        // 由于泛型擦除，T变为Obj和下面的方法签名相同
        /*public boolean equals(T t) {
            return super.equals(t);
        }*/

        @Override
        public boolean equals(Object o) {
            return super.equals(o);
        }

        // 4.不能直接创建泛型实例，需要通过反射
        public <E> void append(List<E> list, Class<E> clz) throws IllegalAccessException, InstantiationException {
            // 无法直接实例化泛型
            /*E e = new E();
            list.add(e);*/
            E elem = clz.newInstance();
            list.add(elem);
        }
    }


    interface A<T> {
        void test(T t);

        void test2(Object object);
    }

    // 为类指定了具体参数，重写的test方法变为String，而接口中的方法参数类型为T
    // 看似违背了多态，编译器会自动生成桥方法，以保证多态性
    class AImpl implements A<String> {

        @Override
        public void test(String s) {

        }

        @Override
        public void test2(Object object) {

        }
    }
}

